package com.zdkj.subway.check.controller.subwayRat.conductorDifferences.shoupiaoyuan;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zdkj.common.core.util.R;
import com.zdkj.common.log.annotation.SysLog;
import com.zdkj.subway.check.controller.CommonController;
import com.zdkj.subway.check.dto.SwAuConductorToBeCheckedDto;
import com.zdkj.subway.check.entity.SwAuConductorToBeChecked;
import com.zdkj.subway.check.entity.SwParamLine;
import com.zdkj.subway.check.entity.SwParamStation;
import com.zdkj.subway.check.enums.ResultDetailMsg;
import com.zdkj.subway.check.mapper.SwAuConductorToBeCheckedMapper;
import com.zdkj.subway.check.mapper.SwParamLineMapper;
import com.zdkj.subway.check.mapper.SwParamStationMapper;
import com.zdkj.subway.check.result.Result;
import com.zdkj.subway.check.service.SwAuConductorToBeCheckedService;
import com.zdkj.subway.check.util.DateFormat;
import com.zdkj.subway.check.util.LocalDateConverter;
import com.zdkj.subway.check.util.LocalDateTimeConverter;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;

/**
 * 线网层级确认-数据协查管理-BOM票款差异协查-售票员票款差异协查
 * 线网层级确认-数据协查管理-BOM票款差异协查-BOM系统差异协查-BOM系统数据
 * 售票员待协查 `
 */
@RestController
@RequestMapping("/checkNew")
@Slf4j
public class SwAuConductorToBeCheckedCtrl {

    @Resource
    private SwAuConductorToBeCheckedService swAuConductorToBeCheckedService;
    @Autowired
    private SwAuConductorToBeCheckedMapper swAuConductorToBeCheckedMapper;
    @Autowired
    private CommonController commonController;
    @Autowired
    private SwParamLineMapper swParamLineMapper;
    @Autowired
    private SwParamStationMapper swParamStationMapper;


    @RequestMapping("/auditShouPiaoYuanPKCYXC")
    @ApiOperation(value = "售票员票款差异协查流程状态修改", notes = "售票员票款差异协查流程状态修改")
    public Result auditShouPiaoYuanPKCYXC(@RequestBody SwAuConductorToBeChecked swAuConductorToBeChecked) {
        return swAuConductorToBeCheckedService.auditShouPiaoYuanPKCYXC(swAuConductorToBeChecked);
    }

    /**
     * 售票员待协查 列表
     * @param jsonObject
     * @return
     */
    @RequestMapping("/getSwAuConductorToBeCheckedList")
    @ApiOperation(value = "售票员待协查 列表", notes = "售票员待协查 列表")
    public Result getSwAuConductorToBeCheckedList(@RequestBody JSONObject jsonObject){
        return swAuConductorToBeCheckedService.getSwAuConductorNoticeList(jsonObject);
    }

    /**
     * 售票员待协查 单独查询
     * @param jsonObject
     * @return
     */
    @RequestMapping("/getSwAuConductorToBeChecked")
    @ApiOperation(value = "售票员待协查 单独查询", notes = "售票员待协查 单独查询")
    public Result getSwAuConductorToBeChecked(@RequestBody JSONObject jsonObject){
        return swAuConductorToBeCheckedService.getSwAuConductorNotice(jsonObject);
    }

    /**
     * 售票员待协查 修改
     * @param jsonObject
     * @return
     */
    @RequestMapping("/updateSwAuConductorToBeCheckedToStatus")
    @ApiOperation(value = "售票员待协查 修改", notes = "售票员待协查 修改")
    @Transactional(rollbackFor = Exception.class)
    public Result updateSwAuConductorToBeCheckedToStatus(@RequestBody JSONObject jsonObject){
        try{
            if(null != jsonObject.getJSONArray("ids")){
                JSONArray ids = jsonObject.getJSONArray("ids");
                for(Object idObj: ids){
                    Integer id = Integer.valueOf(idObj.toString());
                    SwAuConductorToBeChecked swAuConductorToBeChecked = new SwAuConductorToBeChecked();
                    swAuConductorToBeChecked.setId(id);
                    //机电回复状态 客运回复状态
                    if(null != jsonObject.getString("typeTwo")){
                        if("2".equals(jsonObject.getString("typeTwo"))){
                            swAuConductorToBeChecked.setKyReplySatus("1");
                            swAuConductorToBeChecked.setAssistState("3");
                        }else{
                            swAuConductorToBeChecked.setJdReplySatus("1");
                        }
                    }
                    //协查状态
                    swAuConductorToBeChecked.setJdReplyTime(new Date());
                    swAuConductorToBeCheckedMapper.updateById(swAuConductorToBeChecked);
                }
                Map param = JSONObject.parseObject(jsonObject.toString(),Map.class);
                commonController.innerBatch(param);//售票员票款差异在下发协查时就给客运发代办
            }
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new Result(ResultDetailMsg.OK);
    }



    /**
     * 售票员待协查 修改
     * @param jsonObject
     * @return
     */
    @RequestMapping("/updateSwAuConductorToBeCheckedToStatusKY")
    @ApiOperation(value = "售票员待协查 修改", notes = "售票员待协查 修改")
    @Transactional(rollbackFor = Exception.class)
    public Result updateSwAuConductorToBeCheckedToStatusKY(@RequestBody JSONObject jsonObject){
        try{
            if(null != jsonObject.getJSONArray("ids")){
                JSONArray ids = jsonObject.getJSONArray("ids");
                for(Object idObj: ids){
                    Integer id = Integer.valueOf(idObj.toString());
                    SwAuConductorToBeChecked swAuConductorToBeChecked = new SwAuConductorToBeChecked();
                    swAuConductorToBeChecked.setId(id);
                    if(null != jsonObject.getString("typeTwo")){
                        if("2".equals(jsonObject.getString("typeTwo"))){
                            swAuConductorToBeChecked.setKyReplySatus("1");
                        }else{
                            swAuConductorToBeChecked.setJdReplySatus("1");
                        }
                    }
                    swAuConductorToBeChecked.setAssistState("3");
                    swAuConductorToBeChecked.setKyAssistInvestStatus("3");
                    swAuConductorToBeChecked.setKyReplyTime(new Date());
                    swAuConductorToBeCheckedMapper.updateById(swAuConductorToBeChecked);
                }
                Map param = JSONObject.parseObject(jsonObject.toString(),Map.class);
                commonController.innerBatch(param);//售票员票款差异在下发协查时就给客运发代办
            }
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new Result(ResultDetailMsg.OK);
    }
    /**
     * 售票员待协查 修改
     * @param jsonObject
     * @return
     */
    @RequestMapping("/updateSwAuConductorToBeChecked")
    @ApiOperation(value = "售票员待协查 修改", notes = "售票员待协查 修改")
    public Result updateSwAuConductorToBeChecked(@RequestBody JSONObject jsonObject){
        if(null != jsonObject.getJSONArray("ids")){
            JSONArray ids = jsonObject.getJSONArray("ids");
            for(Object idObj: ids){
                Integer id = Integer.valueOf(idObj.toString());
                this.updateSwAuConductorToBeCheckedById(jsonObject,id);
            }
        }else if(null != jsonObject.getInteger("id")){
            Integer id = jsonObject.getInteger("id");
            this.updateSwAuConductorToBeCheckedById(jsonObject,id);
        }
        return new Result(ResultDetailMsg.OK);
    }

    /**
     * 售票员待协查 修改
     * @param jsonObject
     * @param id
     */
    private void updateSwAuConductorToBeCheckedById(JSONObject jsonObject,Integer id){
        String jdReplyReason = jsonObject.getString("jdReplyReason");
        String jdReplyDetail = jsonObject.getString("jdReplyDetail");
        String kyReplyReason = jsonObject.getString("kyReplyReason");
        String kyReplyDetail = jsonObject.getString("kyReplyDetail");
        String replySaleMoney = jsonObject.getString("replySaleMoney");
        String replyRechargeMoney = jsonObject.getString("replyRechargeMoney");
        String replyErrorReturnMoney = jsonObject.getString("replyErrorReturnMoney");
        SwAuConductorToBeChecked swAuConductorToBeChecked = new SwAuConductorToBeChecked();

        swAuConductorToBeChecked.setId(id);
        //客运专业回馈差异原因（字典）
        if(null != kyReplyReason){
            swAuConductorToBeChecked.setKyReplyReason(kyReplyReason);
        }
        //客运专业回馈详情
        if(null != kyReplyDetail){
            swAuConductorToBeChecked.setKyReplyDetail(kyReplyDetail);
        }
        //机电专业回馈差异原因（字典）
        if(null != jdReplyReason){
            swAuConductorToBeChecked.setJdReplyReason(jdReplyReason);
        }
        //机电专业回馈详情
        if(null != jdReplyDetail){
            swAuConductorToBeChecked.setJdReplyDetail(jdReplyDetail);
        }
        //回馈售票金额
        if(null != replySaleMoney){
            swAuConductorToBeChecked.setReplySaleMoney(new BigDecimal(replySaleMoney));
        }
        //回馈充值金额
        if(null != replyRechargeMoney){
            swAuConductorToBeChecked.setReplyRechargeMoney(new BigDecimal(replyRechargeMoney));
        }
        //回馈补票金额
        if(null != replyErrorReturnMoney){
            swAuConductorToBeChecked.setReplyErrorReturnMoney(new BigDecimal(replyErrorReturnMoney));
        }
        swAuConductorToBeCheckedMapper.updateById(swAuConductorToBeChecked);
    }

    /**
     * 导出
     * @param
     * @return
     */
    @ApiOperation(value = "BOM票款系统差异协查导出", notes = "BOM票款系统差异协查导出")
    @GetMapping({"/exportBOMXT"})
    @SysLog("BOM票款系统差异协查导出")
    public void export(String ids,String tag, SwAuConductorToBeChecked params, HttpServletResponse response) throws ParseException {

        List<SwAuConductorToBeCheckedDto> records = new ArrayList<>();
        if (ids == null || ids.isEmpty()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("lineCode", params.getLineCode());
            jsonObject.put("stationCode", params.getStationCode());
            jsonObject.put("equipmentNumber", params.getEquipmentNumber());
            jsonObject.put("conductorPersonName", params.getConductorPersonName());
            jsonObject.put("assistTime", params.getAssistTime());
            jsonObject.put("assistStatess", params.getAssistState());//导出机电协查状态为2，3的数据
            jsonObject.put("kyAssistInvestStatusss", params.getKyAssistInvestStatus());//导出客运协查状态为2，3的数据
            Result result = swAuConductorToBeCheckedService.getSwAuConductorNoticeList(jsonObject);
            Object data = result.getData();
            JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(data));
            String list = jsonObject1.get("list").toString();
            //查询要导出的数据 重新组织
            if (!StringUtils.isEmpty(list)) {
                List<SwAuConductorToBeChecked> objects = JSON.parseArray(list, SwAuConductorToBeChecked.class);
                objects.stream().forEach(x -> {
                    SwAuConductorToBeCheckedDto dto = swAuConductorToBeCheckedDtoCommon(x);
                    records.add(dto);
                });

            }
        }else {
            List<String> idLists = new ArrayList<>();
            String[] idParam = ids.split(",");
            for (String s : idParam) {
                idLists.add(s);
            }
            if (CollectionUtils.isNotEmpty(idLists)) {
                List<SwAuConductorToBeChecked> objects = swAuConductorToBeCheckedMapper.selectBatchIds(idLists);
                objects.stream().forEach(x -> {
                    SwAuConductorToBeCheckedDto dto = swAuConductorToBeCheckedDtoCommon(x);
                    records.add(dto);
                });
            }

        }
        InputStream excelTemplateIs = null;
        try {
            response.reset(); // 非常重要
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = null;
            // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
            // {} 代表普通变量 {.} 代表是list的变量
            //此处getResourceAsStream 用于获取服务器打包后的Excel模板文件流;
            //如果采用getPath方法获取文件地址本地ieda环境可以获取到，上传到服务器后会失效。采用流可以都生效
            //String path = this.getClass().getClassLoader().getResource("templates/XXXX.xlsx").getPath();
            //ExcelWriter excelWriter = EasyExcel.write(ExcelUtils.getOutputStream("XXXX",httpServletResponse)).withTemplate(path).build();
            WriteSheet writeSheet = null;
            if("keyun".equals(tag)){
                fileName = URLEncoder.encode("BOM票款差异客运协查", "UTF-8");
                excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/export/SwAuKeYunBOMXTExcelTemplate.xlsx");
                writeSheet = EasyExcel.writerSheet("BOM票款差异客运协查").build();
            }else {
                fileName = URLEncoder.encode("BOM票款差异机电协查", "UTF-8");
                excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/export/SwAuBOMXTExcelTemplate.xlsx");
                writeSheet = EasyExcel.writerSheet("BOM票款差异机电协查").build();
            }
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                    .registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter())
                    .withTemplate(excelTemplateIs).build();
            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            // 如果数据量大 list不是最后一行 参照另一个
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
            //直接写入Excel数据(list是我查询并需导出的数据，并且里面的字段和excel需要导出的字段对应)
            excelWriter.fill(records, fillConfig, writeSheet);
            excelWriter.finish();


        } catch (Exception e) {
            e.printStackTrace();
            log.error("BOM票款差异协查导出失败");
        } finally {
            if (excelTemplateIs != null) {
                try {
                    excelTemplateIs.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }

    }

    /**
     * 数据组织
     * @param x
     * @return
     */
    private SwAuConductorToBeCheckedDto swAuConductorToBeCheckedDtoCommon(SwAuConductorToBeChecked x) {
        SwParamLine swParamLine = swParamLineMapper.selectOne(Wrappers.<SwParamLine>lambdaQuery().eq(SwParamLine::getCode, x.getLineCode()));
        SwParamStation swParamStation = swParamStationMapper.selectOne(Wrappers.<SwParamStation>lambdaQuery()
                .eq(SwParamStation::getLineCode, x.getLineCode()).eq(SwParamStation::getCode, x.getStationCode()));
        x.setLineCode(swParamLine.getName());
        x.setStationCode(swParamStation.getName());
        x.setPaidAmount(getFixed(x.getPaidAmount()));//BOM实点金额
        x.setSysAmount(getFixed(x.getSysAmount()));//SC系统数据金额
        x.setScSellAmount(getFixed(x.getScSellAmount()));// SC售票
        x.setScInvestAmount(getFixed(x.getScInvestAmount()));// SC充值
        x.setScFaretkAmount(getFixed(x.getScFaretkAmount()));// SC补票
        x.setReplySaleMoney(getFixed(x.getReplySaleMoney()));// SC回馈售票
        x.setReplyRechargeMoney(getFixed(x.getReplyRechargeMoney()));//SC回馈充值
        x.setReplyErrorReturnMoney(getFixed(x.getReplyErrorReturnMoney()));// SC回馈补票
        x.setDiffMoney(getFixed(x.getDiffMoney()));//回馈差异金额

        //机电回馈
        x.setJdReplyReason(StringUtils.isEmpty(x.getJdReplyReason()) ? " " : (x.getJdReplyReason().equals("1") ? "系统原因" : "非系统原因"));
        x.setJdReplyDetail(StringUtils.isEmpty(x.getJdReplyDetail()) ? " " : x.getJdReplyDetail());
        x.setJdReplySatus(StringUtils.isEmpty(x.getJdReplySatus()) ? "未回馈" : (x.getJdReplySatus().equals("0") ? "未回馈" : "已回馈"));

        //客运回馈
        x.setKyReplyReason(StringUtils.isEmpty(x.getKyReplyReason()) ? " " : (x.getKyReplyReason().equals("1") ? "系统原因" : "非系统原因"));
        x.setKyReplyDetail(StringUtils.isEmpty(x.getKyReplyDetail()) ? " " : x.getKyReplyDetail());
        x.setKyReplySatus(StringUtils.isEmpty(x.getKyReplySatus()) ? "未回馈" : (x.getKyReplySatus().equals("0") ? "未回馈" : "已回馈"));

        SwAuConductorToBeCheckedDto dto = new SwAuConductorToBeCheckedDto();
        BeanUtils.copyProperties(x,dto);
        dto.setDiffAmount(getFixed(dto.getPaidAmount().subtract(dto.getSysAmount())));//差异金额
        dto.setRecordDate(DateFormat.DateTurnLocalDate(x.getRecordTime()));//收入日期
        if(x.getAssistTime() != null){
            dto.setAssistDate(DateFormat.DateTurnLocalDate(x.getAssistTime()));//通知时间
        }
        if(x.getJdReplyTime()!=null){
            dto.setJdReplyDateTime(DateFormat.DateTurnLocalDateTime(x.getJdReplyTime()));//机电回馈时间
        }
        if(x.getKyReplyTime()!=null){
            dto.setKyReplyDateTime(DateFormat.DateTurnLocalDateTime(x.getKyReplyTime()));//客运回馈时间
        }
        return dto;
    }

    /**
     * 金额转换
     * @param money
     * @return
     */
    private BigDecimal getFixed(BigDecimal money){
        try {
            BigDecimal num = new BigDecimal("100");
            BigDecimal itemMoney = money.divide(num);
            itemMoney = itemMoney.setScale(2, BigDecimal.ROUND_HALF_UP);
            return itemMoney;

        } catch (Exception e) {
            return new  BigDecimal("0.00");
        }

    }

    /**
     * BOM票款差异机电协查 撤回
     * @param
     * @return
     */
    @RequestMapping("/revokeBomPiaoKuan")
    @ApiOperation(value = "BOM票款差异机电协查 撤回", notes = "BOM票款差异机电协查 撤回")
    public R revokeBomPiaoKuan(String ids) {
        List<SwAuConductorToBeChecked> conductorToBeCheckeds = swAuConductorToBeCheckedMapper.selectBatchIds(Arrays.asList(ids.split(",")));
        if(CollectionUtil.isNotEmpty(conductorToBeCheckeds)){
            for(SwAuConductorToBeChecked conductorToBeChecked:conductorToBeCheckeds){
                if("1".equals(conductorToBeChecked.getReplaceStatus())){
                    return R.failed("已经替换的数据不能撤回！");
                }
                SwAuConductorToBeChecked s=new SwAuConductorToBeChecked();
                s.setId(conductorToBeChecked.getId());
                s.setJdReplySatus("0");//机电回馈状态改为0，未回馈
//                s.setAssistState("2");//协查状态改为2，待协查
                swAuConductorToBeCheckedMapper.updateById(s);
            }
        }
        return R.ok();
    }
}
